﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Xml;
using SHomeWorkshop.LunarPresentation.Adorners;
using SHomeWorkshop.LunarPresentation.Widegets;

namespace SHomeWorkshop.LunarPresentation.Expressions
{
    public abstract class Expression : AdornerDecorator, INotifyPropertyChanged
    {
        private string exID = string.Empty;

        /// <summary>
        /// 获取每个公式都需要有一个唯一标识符，这是为了撤销。
        /// 只有在“重做”时，才应该使用NewExID()方法来设置这个属性的值。
        /// </summary>
        public string ExID
        {
            get { return exID; }
        }

        /// <summary>
        /// 重设一个公式的ID。用于粘贴公式后，避免与源公式ExID重复。
        /// </summary>
        /// <param name="exID">传入ExID。</param>
        /// <returns></returns>
        public bool NewExID(string exID)
        {
            this.exID = exID;
            if (this.xmlData != null)
            {
                if (this.exID != null && this.exID.Length > 0)
                {
                    this.xmlData.SetAttribute("ExID", exID.ToString());
                    return true;
                }
            }
            return false;
        }

        public void LoadXmlExID()
        {
            if (this.xmlData == null) return;

            XmlAttribute attrExid = this.xmlData.GetAttribute("ExID");
            if (attrExid != null)
            {
                this.exID = attrExid.Value;
            }
        }

        public Expression(SubPanel rootPanel, SubPanel parentPanel, Editor editor)
        {
            this.mainBorder = new Border();
            this.Child = this.mainBorder;

            this.mainBorder.Focusable = false;
            this.mainBorder.Background = Brushes.Transparent;
            this.mainBorder.BorderThickness = Globals.defaultBorderThickness;
            this.mainBorder.MouseDown += new MouseButtonEventHandler(mainBorder_MouseDown);

            this.rootPanel = rootPanel;
            this.parentPanel = parentPanel;
            this.editor = editor;
            if (editor != null)
            {
                this.exForeground = editor.DefaultForeground;//Build时会根据XmlData来决定是否更改为自有的值。
            }

            this.HorizontalAlignment = HorizontalAlignment.Left;
            this.VerticalAlignment = VerticalAlignment.Top;

            //System.Diagnostics.Debug.Assert(false, this.GetType().Name);
            //此处可以得到“SubPanel”。

            #region 多路绑定，实现左缩进。
            BuildIndentBinding(parentPanel, editor);
            #endregion

            AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this.mainBorder);
            selectAdorner = new SelectionAdorner(this.mainBorder, this);

            if (isSelected)
            {
                selectAdorner.Visibility = Visibility.Visible;
            }
            else
            {
                selectAdorner.Visibility = Visibility.Hidden;
            }

            selectAdorner.Cursor = System.Windows.Input.Cursors.Hand;
            selectAdorner.MouseLeftButtonDown +=
                new MouseButtonEventHandler(selectAdorner_MouseLeftButtonDown);
            selectAdorner.MouseRightButtonDown +=
                new MouseButtonEventHandler(selectAdorner_MouseRightButtonDown);

            // 因为公式未被选中时，装饰器处于隐藏状态，所以没有必要添加MouseleftButtonUp事件。

            adornerLayer.Add(selectAdorner);

            //左缩进装饰器。
            indentAdorner = new IndentAdorner(this.mainBorder, this);
            adornerLayer.Add(indentAdorner);
        }

        private void BuildIndentBinding(SubPanel parentPanel, Editor editor)
        {
            if (this is SubPanel == false)
            {
                MultiBinding mBinding = new MultiBinding();
                Binding fsBinding = new Binding("ExFontSize");
                fsBinding.Source = editor;

                Binding indentBinding = new Binding("Indent");
                indentBinding.Source = this;

                directBinding = new Binding("Direction");
                directBinding.Source = parentPanel;

                mBinding.Bindings.Add(fsBinding);
                mBinding.Bindings.Add(indentBinding);
                mBinding.Bindings.Add(directBinding);

                mBinding.Converter = Globals.marginConverter;

                BindingOperations.SetBinding(this, MarginProperty, mBinding);

                // 防止在水平子面板中新添加公式位置不准。
                UpdateAlignment();
            }
        }

        private Binding directBinding;

        void selectAdorner_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            //除非提供右键菜单，否则暂时不需要其它内容。
            e.Handled = true;
        }

        /// <summary>
        /// 在程序主窗口被非激活时，禁止下一次鼠标选取操作。
        /// ——这是考虑到弹出消息框后用鼠标点击消息框按钮后会擅自更改“当前选中”的公式。
        /// </summary>
        public static bool forbiddenNextTimeExSelectting = false;

        void mainBorder_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (Editor == null) return;

            if (Editor != Globals.selectedEditor) return;

            if (Expressions.Expression.forbiddenNextTimeExSelectting)
            {
                Expressions.Expression.forbiddenNextTimeExSelectting = false;
                return;
            }
            //防止消息框弹出后首次点击时擅自更改“当前公式”。

            if (this is Expressions.SubPanel == false)
            {
                Editor.SelectedExpression = this;
            }
            else
            {
                Expressions.SubPanel gp = this as Expressions.SubPanel;
                if (gp.SkipSelect)
                {
                    Editor.SelectedExpression = gp.ParentExpression;
                }
                else
                {
                    Editor.SelectedExpression = gp;
                }
            }
            e.Handled = true;
        }

        void selectAdorner_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Globals.dragSourceExpression = this;
            e.Handled = true;
        }

        private SelectionAdorner selectAdorner;

        public SelectionAdorner SelectAdorner
        {
            get { return selectAdorner; }
        }

        public void RefreshSelectAdorner()
        {
            if (selectAdorner == null) return;
            selectAdorner.InvalidateVisual();
        }

        protected IndentAdorner indentAdorner;

        public IndentAdorner IndentAdorner { get { return indentAdorner; } }

        protected Border mainBorder;

        public Border MainBorder
        {
            get { return mainBorder; }
        }

        protected string chineseName = "公式";

        /// <summary>
        /// 公式类型名（中文）。
        /// </summary>
        public virtual string ChineseName
        {
            get { return chineseName; }
        }

        /// <summary>
        /// 公式类型名（英文）。
        /// </summary>
        public string ClassName
        {
            get { return this.GetType().Name; }
        }

        private SubPanel parentPanel;

        public SubPanel ParentPanel
        {
            get { return parentPanel; }
            set
            {
                if (parentPanel != value)
                {
                    parentPanel = value;

                    //重建绑定。
                    BuildIndentBinding(parentPanel, editor);
                }
            }
        }

        private int borderWidth = 1;

        /// <summary>
        /// 默认值：1。
        /// </summary>
        public int BorderWidth
        {
            get { return borderWidth; }
            set
            {
                borderWidth = value;
                if (xmlData != null)
                {
                    this.XmlData.SetAttribute("BorderWidth", borderWidth.ToString());
                }

                this.mainBorder.BorderThickness = new Thickness(borderWidth);
                this.Editor.IsModified = true;
            }
        }

        /// <summary>
        /// 保留这个字段目的是用在IsSelected属性改变时恢复边框色。
        /// </summary>
        protected Brush borderColor = Brushes.Transparent;

        /// <summary>
        /// 自定义边框色属性。对原有的BorderBrush进行了封装。
        /// 这个值并不一定等于MainBorder的BorderBrush，因为有些公式
        /// （如网格式）会有“自动边框色”。
        /// </summary>
        public Brush BorderColor
        {
            get { return borderColor; }
            set
            {
                this.borderColor = value;

                if (value == null)
                {
                    this.mainBorder.BorderBrush = Brushes.Transparent;
                }
                else
                {
                    this.mainBorder.BorderBrush = value;
                }

                this.XmlData.SetAttribute("BorderColor", ColorPicker.GetBrushName(value));
                Editor.IsModified = true;
            }
        }

        private XmlNode xmlData;

        /// <summary>
        /// 公式的后台Xml数据。
        /// </summary>
        public XmlNode XmlData
        {
            get { return xmlData; }
            set
            {
                xmlData = value;
                BuildChildren();
            }
        }

        protected SubPanel rootPanel;

        /// <summary>
        /// 如果公式本身就是“根面板”，则该属性值应为null或自身。
        /// 考虑到拖动之类的操作，无法设置为只读属性。
        /// </summary>
        public SubPanel RootPanel
        {
            get { return rootPanel; }
        }

        protected Editor editor;

        public Editor Editor
        {
            get { return this.editor; }
        }

        protected Brush exForeground = Brushes.White;

        public virtual Brush ExForeground
        {
            get { return exForeground; }
            set
            {
                exForeground = value;

                UpdateExForegroundToXmlData(value);
                //UpdateExForegroundWithoutXmlChanging(value);

                OnForegroundChanged(this, new ForegroundChangedEventArgs() { NewBrush = value });
                Editor.IsModified = true;
                OnPropertyChanged(this, new PropertyChangedEventArgs("ExForeground"));
            }
        }

        /// <summary>
        /// 刷新前景色，但不写入Xml数据。
        /// </summary>
        public virtual void UpdateExForegroundWithoutXmlChanging(Brush value)
        {
            exForeground = value;
        }

        /// <summary>
        /// 将前景色写入Xml数据。
        /// </summary>
        /// <param name="value"></param>
        protected void UpdateExForegroundToXmlData(Brush value)
        {
            if (this.xmlData != null)
            {
                this.xmlData.SetAttribute("ExForeground", ColorPicker.GetBrushName(exForeground));
            }
        }

        private Brush exBackground = Brushes.Transparent;

        public Brush ExBackground
        {
            get { return exBackground; }
            set
            {
                exBackground = value;
                this.mainBorder.Background = exBackground;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute("ExBackground", ColorPicker.GetBrushName(exBackground));
                }
                OnBackgroundChanged(this, new BackgroundChangedEventArgs() { NewBrush = value });
                Editor.IsModified = true;
                OnPropertyChanged(this, new PropertyChangedEventArgs("ExBackground"));
            }
        }

        /// <summary>
        /// 此方法总是由“XmlData”属性的set访问器来调用，而不能手工调用。
        /// 
        /// 读取、显示公式内部各子级公式。
        /// Expression类没有“基面板”，因此“清除基面板中所有控件”
        /// 这步应由各公式自身实现。
        /// </summary>
        protected virtual void BuildChildren()
        {
            // 读取、显示公式内部各子级公式。
            if (xmlData == null) return;

            XmlAttribute attrExID = xmlData.GetAttribute("ExID");
            if (attrExID != null && attrExID.Value.Length > 10)//如果有，按文档中定义的为准。如果还未设置，则按自定的为准。
            {
                this.exID = attrExID.Value;
            }
            else
            {
                this.exID = Guid.NewGuid().ToString();
                this.xmlData.SetAttribute("ExID", this.exID);
            }

            XmlAttribute attrForeground = XmlData.GetAttribute("ExForeground");
            if (attrForeground != null)
            {
                Brush brush = ColorPicker.GetBrushByName(attrForeground.Value);

                this.exForeground = brush;
                UpdateExForegroundWithoutXmlChanging(brush);
                OnForegroundChanged(this, new ForegroundChangedEventArgs() { NewBrush = brush });
                OnPropertyChanged(this, new PropertyChangedEventArgs("ExForeground"));
            }

            XmlAttribute attrExBackground = xmlData.GetAttribute("ExBackground");
            if (attrExBackground != null)
            {
                this.exBackground = ColorPicker.GetBrushByName(attrExBackground.Value);
                OnBackgroundChanged(this, new BackgroundChangedEventArgs() { NewBrush = this.exBackground });
                OnPropertyChanged(this, new PropertyChangedEventArgs("ExBackground"));
                this.mainBorder.Background = this.exBackground;
            }

            XmlAttribute attrBorderWidth = xmlData.GetAttribute("BorderWidth");
            if (attrBorderWidth != null)
            {
                this.borderWidth = int.Parse(attrBorderWidth.Value);
                this.mainBorder.BorderThickness = new Thickness(this.borderWidth);
            }

            XmlAttribute attrBorderColor = xmlData.GetAttribute("BorderColor");
            if (attrBorderColor != null)
            {
                Brush bsh = ColorPicker.GetBrushByName(attrBorderColor.Value);
                this.borderColor = bsh;
                this.mainBorder.BorderBrush = bsh;
            }

            XmlAttribute attrRotateNumber = xmlData.GetAttribute("RotateNumber");
            if (attrRotateNumber != null)
            {
                this.rotateNumber = double.Parse(attrRotateNumber.Value);
                RefreshRotateTransform();
            }

            XmlAttribute attrIndent = xmlData.GetAttribute("Indent");
            if (attrIndent != null)
            {
                this.indent = int.Parse(attrIndent.Value);
                OnPropertyChanged(this, new PropertyChangedEventArgs("Indent"));
                // 绑定，必须调用。
            }

            XmlAttribute attrAlign = xmlData.GetAttribute("Align");
            if (attrAlign != null)
            {
                this.align = (Alignment)Enum.Parse(typeof(Alignment), attrAlign.Value);
                UpdateAlignment();
            }

            XmlAttribute attrComment = xmlData.GetAttribute("CommentText");
            if (attrComment != null)
            {
                this.commentText = attrComment.Value;
                if (this.commentText != null || this.commentText.Length > 0)
                {
                    this.selectAdorner.ToolTip = this.commentText;
                }

                OnPropertyChanged(this, new PropertyChangedEventArgs("CommentText"));
            }
        }

        public static RotateTransform defRotateTransform = new RotateTransform(0);

        protected double rotateNumber = 0;

        public double RotateNumber
        {
            get { return rotateNumber; }
            set
            {
                rotateNumber = value;

                if (value < -180) rotateNumber = -180;
                else if (value > 180) rotateNumber = 180;
                else rotateNumber = value;

                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute("RotateNumber", rotateNumber.ToString());
                }

                RefreshRotateTransform();
            }
        }

        public void RefreshRotateTransform()
        {
            if (rotateNumber == 0)
            {
                this.LayoutTransform = defRotateTransform;
            }
            else
            {
                RotateTransform r = this.LayoutTransform as RotateTransform;

                if (r != null && r.Angle == rotateNumber) return;

                this.LayoutTransform = new RotateTransform(rotateNumber);
            }
        }

        protected List<SubPanel> subPanels;

        /// <summary>
        /// 用以在公式各层间导航，不是所有公式内部都嵌入子面板的。
        /// 因此这个属性可能为空。
        /// </summary>
        public virtual List<SubPanel> SubPanels
        {
            get { return subPanels; }
        }

        protected SubPanel firstSubPanel;

        /// <summary>
        /// 用以在公式各层间导航，不是所有公式内部都嵌入子面板的。
        /// 因此这个属性可能为空。
        /// </summary>
        public virtual SubPanel FirstSubPanel
        {
            get { return firstSubPanel; }
        }

        protected SubPanel lastSubPanel;

        /// <summary>
        /// 用以在公式各层间导航，不是所有公式内部都嵌入子面板的。
        /// 因此这个属性可能为空。
        /// </summary>
        public virtual SubPanel LastSubPanel
        {
            get { return lastSubPanel; }
        }

        protected bool isSelected = false;

        public virtual bool IsSelected
        {
            get { return isSelected; }
            set
            {
                //if (isSelected != value)//多这一句会造成撤销等操作后，无法选中此公式。
                //{
                isSelected = value;
                if (isSelected)
                {
                    selectAdorner.Visibility = Visibility.Visible;
                }
                else
                {
                    selectAdorner.Visibility = Visibility.Hidden;
                }
                //}
            }
        }

        protected string commentText = null;

        public virtual string CommentText
        {
            get { return commentText; }
            set
            {
                if (commentText == value) return;

                commentText = value;

                if (xmlData != null)
                {
                    xmlData.SetAttribute("CommentText", commentText);
                }

                selectAdorner.InvalidateVisual();
                selectAdorner.UpdateLayout();

                Editor.IsModified = true;
                if (this.commentText == null || this.commentText.Length <= 0)
                {
                    this.selectAdorner.ToolTip = null;
                }
                else
                {
                    this.selectAdorner.ToolTip = this.commentText;
                }

                if (Editor.ParentWindow != null && Editor == Globals.selectedEditor)
                {
                    int lastIndex = Editor.ParentWindow.expressionsTreeListPanel.Children.Count - 1;
                    if (lastIndex >= 0)
                    {
                        if (Editor.ParentWindow.expressionsTreeListPanel.Children[lastIndex] is ExpressionLayerButton)
                        {
                            ExpressionLayerButton eb = Editor.ParentWindow.expressionsTreeListPanel.Children[lastIndex] as ExpressionLayerButton;
                            if (eb.CorrespondingExpression == this)
                            {
                                eb.BorderBrush = Brushes.Red;
                                if (commentText != null && commentText.Length > 10)
                                {
                                    eb.ToolTip = commentText.Substring(0, 10) + "...";
                                }
                                else
                                {
                                    eb.ToolTip = commentText;
                                }
                            }
                        }
                    }
                }

                OnPropertyChanged(this, new PropertyChangedEventArgs("CommentText"));
            }
        }

        private int indent = 0;

        /// <summary>
        /// 左缩进。值取[0，6]计七级，0级为无缩进。
        /// </summary>
        public virtual int Indent
        {
            get { return indent; }
            set
            {
                if (value >= 0 && value <= 6)
                {
                    indent = value;

                    if (xmlData != null)
                    {
                        this.XmlData.SetAttribute("Indent", indent.ToString());
                    }

                    RefreshIndent();
                }
            }
        }

        private void RefreshIndent()
        {
            OnPropertyChanged(this, new PropertyChangedEventArgs("Indent"));

            OnIndentChanged(this, new IndentChangedEventArgs()
            {
                NewIndent = indent
            });

            this.Editor.IsModified = true;
            this.indentAdorner.InvalidateVisual();
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        protected void OnPropertyChanged(object sender,
            PropertyChangedEventArgs e)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(sender, e);
            }
        }

        public enum Alignment { Default, LeftOrTop, Center, RightOrBottom }

        protected Alignment align = Alignment.Default;

        public virtual Alignment Align
        {
            get { return align; }
            set
            {
                if (align != value)
                {
                    align = value;
                    if (this.xmlData != null)
                    {
                        this.xmlData.SetAttribute("Align", align.ToString());
                    }

                    UpdateAlignment();
                    Editor.IsModified = true;
                }
            }
        }

        public virtual void UpdateAlignment()
        {
            if (ParentPanel != null && !(this is SubPanel))// 子面板本身是不需要考虑对齐方式的。
            {
                if (ParentPanel.Direction == Orientation.Horizontal)
                {
                    switch (align)
                    {
                        case Alignment.LeftOrTop:
                            {
                                this.VerticalAlignment = VerticalAlignment.Top; break;
                            }
                        case Alignment.Center:
                            {
                                this.VerticalAlignment = VerticalAlignment.Center; break;
                            }
                        case Alignment.RightOrBottom:
                            {
                                this.VerticalAlignment = VerticalAlignment.Bottom; break;
                            }
                        default:
                            {
                                switch (parentPanel.Align)
                                {
                                    case Alignment.Center:
                                        {
                                            this.VerticalAlignment = VerticalAlignment.Center;
                                            break;
                                        }
                                    case Alignment.LeftOrTop:
                                        {
                                            this.VerticalAlignment = VerticalAlignment.Top;
                                            break;
                                        }
                                    case Alignment.RightOrBottom:
                                        {
                                            this.VerticalAlignment = VerticalAlignment.Bottom;
                                            break;
                                        }
                                    default:
                                        {
                                            if (parentPanel == this.RootPanel)
                                            {
                                                this.VerticalAlignment = VerticalAlignment.Top;
                                                // 当前公式在根面板中。
                                                // 根面板水平对齐时，则默认并不按居中，而是按Top对齐。
                                            }
                                            else
                                            {
                                                this.VerticalAlignment = VerticalAlignment.Center;
                                                // 水平子面板中的公式，默认居中对齐。
                                            }
                                            break;
                                        }
                                }
                                break;
                            }
                    }
                }
                else if (ParentPanel.Direction == Orientation.Vertical)
                {
                    switch (align)
                    {
                        case Alignment.LeftOrTop:
                            {
                                this.HorizontalAlignment = HorizontalAlignment.Left; break;
                            }
                        case Alignment.Center:
                            {
                                this.HorizontalAlignment = HorizontalAlignment.Center; break;
                            }
                        case Alignment.RightOrBottom:
                            {
                                this.HorizontalAlignment = HorizontalAlignment.Right; break;
                            }
                        default:
                            {
                                switch (parentPanel.align)
                                {
                                    case Alignment.Center:
                                        {
                                            this.HorizontalAlignment = HorizontalAlignment.Center;
                                            break;
                                        }
                                    case Alignment.LeftOrTop:
                                        {
                                            this.HorizontalAlignment = HorizontalAlignment.Left;
                                            break;
                                        }
                                    case Alignment.RightOrBottom:
                                        {
                                            this.HorizontalAlignment = HorizontalAlignment.Right;
                                            break;
                                        }
                                    default:
                                        {
                                            this.HorizontalAlignment = HorizontalAlignment.Left;
                                            break;
                                            // 垂直子面板中的公式，默认左对齐。
                                        }
                                }

                                break;
                            }
                    }
                }

                //只有左齐时才支持，其它方式对齐要取消编号，水平子面板也要取消。
                //因此要在此处刷新。
                ParentPanel.RefreshAutoNumbersOfBaseText();
            }
        }

        /// <summary>
        /// 一次公式级的撤销操作。
        /// </summary>
        /// <param name="action">一次撤销或重做可以涉及到多个公式（因而包含多次公式级的撤销或重做）。</param>
        public virtual void Undo(Action action)
        {
            if (action != null)
            {
                SetProperty(action.Name, action.OldValue);
            }
        }

        /// <summary>
        /// 一次公式级的重做操作。
        /// </summary>
        /// <param name="action"></param>
        public virtual void Redo(Action action)
        {
            if (action != null)
            {
                SetProperty(action.Name, action.NewValue);
            }
        }

        /// <summary>
        /// 索引值区间为[０，最大索引]。这个方法不同于插入方法。
        /// </summary>
        /// <param name="newIndex">不能取Count数。最大只能是Count－１.</param>
        /// <returns></returns>
        public bool MoveTo(int newIndex)
        {
            if (this is Expressions.SubPanel) return false;
            if (newIndex < 0) return false;

            if (this.ParentPanel == null) return false;

            StackPanel sPanel = this.parentPanel.BasePanel;

            if (newIndex >= sPanel.Children.Count) return false;

            int curIndex = sPanel.Children.IndexOf(this);

            if (newIndex != curIndex)
            {
                sPanel.Children.Remove(this);
                sPanel.Children.Insert(newIndex, this);
                return true;
            }
            else return false;
        }

        /// <summary>
        /// 根据属性名称取实现类中某个属性。
        /// </summary>
        /// <param name="propertyName">属性名（以字符串形式表示）。</param>
        /// <param name="value">属性值（以字符串形式表示）。</param>
        public virtual void SetProperty(string propertyName, string value)
        {
            switch (propertyName)
            {
                case "BorderColor":
                    {
                        if (value == "UnKnown")
                        {
                            this.BorderColor = null;
                        }
                        else
                        {
                            this.BorderColor = ColorPicker.GetBrushByName(value);
                        }
                        break;
                    }
                case "BorderWidth":
                    {
                        this.BorderWidth = int.Parse(value);
                        break;
                    }
                case "CommentText":
                    {
                        this.CommentText = value;
                        break;
                    }
                case "Align":
                    {
                        //2011年7月2日尝试添加子面板对其中公式的默认对齐。
                        //if (this is Expressions.SubPanel) break;//子面板无所谓对齐。

                        this.Align = (Alignment)Enum.Parse(typeof(Alignment), value);
                        break;
                    }
                case "Indent":
                    {
                        if (this is Expressions.SubPanel) break;//子面板无所谓左缩进层级。

                        this.Indent = int.Parse(value);
                        break;
                    }
                case "OutXmlText":
                    {
                        XmlNode newNode = XmlTools.ReplaceOutXmlText(this.XmlData, value);
                        if (newNode != null)
                        {
                            this.XmlData = newNode;
                        }
                        break;
                    }
                case "ExBackground":
                    {
                        this.ExBackground = ColorPicker.GetBrushByName(value);
                        break;
                    }
                case "ExForeground":
                    {
                        this.ExForeground = ColorPicker.GetBrushByName(value);
                        break;
                    }
                case "RotateNumber":
                    {
                        this.RotateNumber = double.Parse(value);
                        break;
                    }
            }
        }

        /// <summary>
        /// 此方法为指定公式及其子级公式生成新的ExID。
        /// 应在粘贴公式（或相似情况）后调用。
        /// 撤销“删除”操作不应调用本方法。重做“插入”操作也不应调用本方法。
        /// </summary>
        /// <param name="ex"></param>
        public static void RebuildAllExIDs(Expressions.Expression ex)
        {
            if (ex == null) return;

            ex.NewExID(Guid.NewGuid().ToString());

            if (ex is Expressions.SubPanel)
            {
                Expressions.SubPanel panel = ex as Expressions.SubPanel;
                foreach (UIElement ue in panel.BasePanel.Children)
                {
                    Expressions.Expression subEx = ue as Expressions.Expression;

                    if (subEx != null)
                    {
                        RebuildAllExIDs(subEx);
                    }
                }

            }
            else
            {
                if (ex.SubPanels != null && ex.SubPanels.Count > 0)
                {
                    foreach (Expressions.SubPanel panel in ex.SubPanels)
                    {
                        RebuildAllExIDs(panel);
                    }
                }
            }
        }

        /// <summary>
        /// 此字段只用于标题文本块刷新折叠状态。
        /// jurisdiction,意为“管辖权”。
        /// </summary>
        public bool jurisdiction = false;

        public event EventHandler<ForegroundChangedEventArgs> ForegroundChanged;

        public event EventHandler<BackgroundChangedEventArgs> BackgroundChanged;

        protected void OnForegroundChanged(object sender, ForegroundChangedEventArgs e)
        {
            if (ForegroundChanged != null)
            {
                ForegroundChanged(sender, e);
            }
        }

        protected void OnBackgroundChanged(object sender, BackgroundChangedEventArgs e)
        {
            if (BackgroundChanged != null)
            {
                BackgroundChanged(sender, e);
            }
        }

        public event EventHandler<IndentChangedEventArgs> IndentChanged;

        protected void OnIndentChanged(object sender, IndentChangedEventArgs e)
        {
            if (this.IndentChanged != null)
            {
                this.IndentChanged(sender, e);
            }
        }
    }

    public class ForegroundChangedEventArgs : EventArgs
    {
        public Brush NewBrush { get; set; }
    }

    public class BackgroundChangedEventArgs : EventArgs
    {
        public Brush NewBrush { get; set; }
    }

    public class IndentChangedEventArgs : EventArgs
    {
        public int NewIndent { get; set; }
    }
}
